import base64
import json
import random
from copy import copy

from gmssl import sm2
import requests
from base64 import b64encode
import os
from datetime import datetime
import time

from userAgent import generate_user_agents
from dbHelp import DbHelp
from utils import Utils
from config import Config
from utils.chaojiying_Python.chaojiying import Chaojiying_Client

"""江西省补贴性线上职业技能培训管理平台(刷课系统)"""
class FlashClass(DbHelp):
    def __init__(self, idCar, pwd, nickName, token, miaomiao):
        self.logger = self.loggerHandlerInit("flashClass")
        super().__init__(self.logger) # 初始化数据库
        self.idCar = idCar
        self.pwd = pwd
        self.nickName = nickName
        self.session = requests.Session()
        self.UrlPool = self.iniApi()
        self.requestErrorTime = 5 # 统一重新请求时间
        self.accessToken = token
        self.allDoneClass = [] # 未完成课程
        self.miaomiao = miaomiao


    def loggerHandlerInit(self,logFileName):
        """初始化日志处理器"""
        import logging
        logger = logging.getLogger(logFileName)
        logger.setLevel(logging.DEBUG)
        file_handler = logging.FileHandler(os.path.basename(__file__).replace(".py", ".log"), encoding="utf-8")
        console_handler = logging.StreamHandler()
        logger.addHandler(file_handler)
        logger.addHandler(console_handler)
        return logger

    def calculate_execution_time(self, msg):
        """时间计时器"""
        def iniApi(func):
            def wrapper(self, *args, **kwargs):
                if msg:
                    self.logger.info(f"时间:{Utils.getFormatted_datetime_now()},当前刷课用户: {self.nickName}, 方法名 {func.__name__}: 时间: {self.getNowTime()}, info: 正在初始化 {msg}...")
                else:
                    self.logger.info(f"时间:{Utils.getFormatted_datetime_now()},当前刷课用户: {self.nickName}, 方法名 {func.__name__}: 时间: {self.getNowTime()}, info: 正在初始化 {func.__name__}...")
                start_time = time.time()
                result = func(self, *args, **kwargs)
                end_time = time.time()
                execution_time = (end_time - start_time)
                self.logger.info(f"时间:{Utils.getFormatted_datetime_now()},当前刷课用户: {self.nickName}, 方法名 {func.__name__}: 时间: {self.getNowTime()}, info: {msg if msg else func.__name__}加载完成,耗时时间为: {execution_time:.3f} 秒")
                return result
            return wrapper
        return iniApi

    def getNowTime(self):
        """获取系统当前时间"""
        current_datetime = datetime.now()
        formatted_date_time = current_datetime.strftime("%Y-%m-%d %H:%M:%S")
        return formatted_date_time

    @calculate_execution_time(1, "发送请求获取响应")
    def guaranteeRequest(self, method, url, **kwargs):
        """保证每次的请求都是正常"""
        try:
            if method == 'GET':
                response = self.session.get(url, **kwargs)
                self.logger.info(f"时间:{Utils.getFormatted_datetime_now()},当前刷课用户: {self.nickName}, 当前: {url} 请求成功")
                return response
            elif method == 'POST':
                response = self.session.post(url, **kwargs)
                self.logger.info(f"时间:{Utils.getFormatted_datetime_now()},当前刷课用户: {self.nickName}, 当前: {url} 请求成功")
                return response
            else:
                self.logger.debug(f"时间:{Utils.getFormatted_datetime_now()},当前刷课用户: {self.nickName}, 不支持的请求方法: {method}")
                raise ValueError(f"时间:{Utils.getFormatted_datetime_now()},当前刷课用户: {self.nickName}, 不支持的请求方法: {method}")
        except Exception as e:
            self.logger.debug(f"时间:{Utils.getFormatted_datetime_now()},当前刷课用户: {self.nickName}, 当前: {url} 请求出现异常{e}, 正在等待5秒后重试....")
            self.unifiedErrorSleep()  # 等待时间后后重新请求
            self.guaranteeRequest(method, url, **kwargs)  # 如果获取失败则重新获取
    # @calculate_execution_time(1,"Url地址池")
    def iniApi(self):
        """初始化Url地址池"""
        return {
            "loginPublicUrl": "https://api.cloud.wozhipei.com/auth/user/v1/public_key", # 获取公钥
            "loginUrl": "https://api.cloud.wozhipei.com/auth/user/v1/login", # 用户登录认证
            "updateTokenUrl": "https://apif.wozhipei.com/users/update-access-token", # 更新Token信息
            "studyUrl": "https://apif.wozhipei.com/student-center/study", # 获取课程列表
            "previewUrl": "https://apif.wozhipei.com/courses/test-preview?course_id={courseId}&class_id={class_id}", # 获取课程列表
            "updateProgress":"https://apistudy.wozhipei.com/studies/study?video_id={video_id}&u={u}&time={time}&unit_id={unit_id}&class_id={class_id}",
            "videDetails": "https://apif.wozhipei.com/course-units/{unit_id}?class_id={class_id}",
            "supervisesCode": "https://apif.wozhipei.com/supervises/code",
            "smartNew": "https://apif.wozhipei.com/supervises/smart-new",
        }

    # @calculate_execution_time(1, "获取加密公钥")
    def getPublicKey(self):
        """获取公钥"""
        self.setSessionHeaders({
            'User-Agent': random.choice(generate_user_agents(100))
        })
        response = self.guaranteeRequest("GET", self.UrlPool.get("loginPublicUrl"), headers=self.session.headers)
        if response.json()['messageCode'] == "200":
            publicKey = response.json()['data']
            self.logger.info(f"时间:{Utils.getFormatted_datetime_now()},当前刷课用户: {self.nickName}, {self.getNowTime()}, 登录接口的公钥获取完毕。")
            return publicKey
        else:
            """5秒后重新获取Key"""
            self.unifiedErrorSleep()
            self.getPublicKey()

    # @calculate_execution_time(1, "统一添加请求头信息")
    def setSessionHeaders(self, items):
        """统一添加请求头信息"""
        for k, v in items.items():
            self.session.headers[k] = v

    # @calculate_execution_time(1, "统一错误请求等待时间")
    def unifiedErrorSleep(self):
        """统一错误请求等待时间"""
        time.sleep(self.requestErrorTime)

    # @calculate_execution_time(1, "用户登录获取")
    def getLoginToken(self, publicKey):
        """用户登录获取tokne"""
        def encrypt():
            data_str = self.pwd
            data_bytes = data_str.encode('utf-8')
            encoded_data = b64encode(data_bytes)
            sm2_crypt = sm2.CryptSM2(public_key=publicKey, private_key="", mode=1)
            return sm2_crypt.encrypt(encoded_data).hex()
        encryptData = encrypt()
        data = {
            "account": self.idCar,
            "appKey": "WEB",
            "sid": 1018,
            "type": 1,
            "authOpenId": "",
            "authType": "",
            "publicKey": publicKey,
            "password": encryptData
        }
        response = self.guaranteeRequest("POST", self.UrlPool.get("loginUrl"), headers=self.session.headers, json=data)
        data = response.json()
        if data['messageCode'] == "200":
            accessToken = data['data']['accessToken']
            self.accessToken = accessToken # 设置全局token
            self.setSessionHeaders({
                'Authorization': f"Bearer {accessToken}"
            })
            return f"Bearer {accessToken}"
        else:
            self.logger.debug(f"时间:{Utils.getFormatted_datetime_now()},当前刷课用户: {self.nickName}, 当前: 登录失败 响应结果:{data}\n 请求信息{data} 正在等待5秒后重试....")

            self.unifiedErrorSleep()
            self.getLoginToken(self.getPublicKey())

    # @calculate_execution_time(1, "获取解析课程安排")
    def getStudentStudy(self):
        """获取课程安排"""
        headers = {
            "Host": "apif.wozhipei.com",
            "Origin": "https://admin-jiangxi.zhipeizaixian.com",
            "X-User-Type": "1",
        }
        newHeaders = {**self.session.headers, **headers}

        response = self.guaranteeRequest("GET", self.UrlPool['studyUrl'], headers=newHeaders)
        print("状态: ", response.status_code)
        print(f"时间:{Utils.getFormatted_datetime_now()},当前刷课用户: {self.nickName}, 获取课程安排的头: ", newHeaders)
        if response.status_code == 200:
            studentStudy = response.json()
            uid = studentStudy[0]['uid'] # uuid
            class_id = studentStudy[0]['courseStat']['on']["course"][0]['class_id'] # 教室Id
            courseId = studentStudy[0]['courseStat']['on']["course"][0]['course']['id'] # 课程ID
            data = {
                "uid":uid,
                "class_id":class_id,
                "courseId":courseId
            }
            return data
        elif response.status_code == 401:
            publicKey = self.getPublicKey()
            self.getLoginToken(publicKey)
            self.updateAccessToken()
            return self.getStudentStudy()
        else:
            self.logger.debug(f"时间:{Utils.getFormatted_datetime_now()},当前刷课用户: {self.nickName}, 当前: 获取课程安排失败 响应结果:{response.content} 正在等待5秒后重试....")
            self.unifiedErrorSleep()
            return self.getStudentStudy()

    # @calculate_execution_time(1, "获取视频详情")
    def getVideDetaile(self,unit_id, class_id):
        """获取视频详情"""
        headers = {
            "Host": "apif.wozhipei.com",
            "Origin": "https://admin-jiangxi.zhipeizaixian.com",
            "Sec-Fetch-Dest": "empty",
            "Sec-Fetch-Mode": "cors",
            "Sec-Fetch-Site": "cross-site",
            "X-Client-Type": "pc",
            "X-Site-Alias": "jx",
            "X-User-Type": "1",
        }
        newHeaders = {**self.session.headers, **headers}

        response = self.guaranteeRequest("GET",self.UrlPool.get("videDetails").format(
            unit_id=unit_id,
            class_id=class_id
        ), headers=newHeaders)
        if response.status_code == 200:
            details = response.json()
            vide_id = details['video']['id']
            return vide_id

        else:
            content = response.content.decode("utf-8")
            self.logger.debug(f"时间:{Utils.getFormatted_datetime_now()},当前刷课用户: {self.nickName}, 当前: 获取视频详情失败 响应结果:{content} 正在等待5秒后重试....")
            self.unifiedErrorSleep()
            self.getVideDetaile(unit_id, class_id)

    # @calculate_execution_time(1, "获取全部课组")
    def getAllcoursesPreview(self, classInfo):
        """获取全部课组"""
        def analysisPreview(classDetile, class_id):
            courses = classDetile["course"]
            print(courses)
            for course in courses:
                # 每一组，有两层, 第二层才是刷课数据
                # print(f"当前正在刷的是 {course['title']} 分组")
                for unit in course['units']:
                    progress_time = unit['progress_time']  # 当前播放进度时常
                    total_time = unit['total_time']  # 总进度时常
                    title = unit['title']  # 视频名称
                    chapter_id = unit['chapter_id']  # 章节 ID
                    id = unit['id']  # 视频id
                    video_id = self.getVideDetaile(id, classInfo.get('class_id'))
                    alldone = {
                        "idCar": self.idCar, # 视频者的账号
                        "uid": classInfo.get("uid"), # 更新进度Id
                        "id": id, # 课程Id
                        "chapter_id": chapter_id, # 章节 ID
                        "title": title, # 课程名称
                        "progress_time": progress_time, # 当前播放进度
                        "total_time":total_time, #总进度
                        "video_id":video_id, #视频Id
                        "class_id":class_id, #教室Id
                        "course_id":classInfo.get("courseId"), #教室Id
                    }
                    self.allDoneClass.append(alldone) # 保存所有进度

            self.delAllDbProgress(self.idCar) # 所有进度入库前先删除所有数据
            self.saveDbProgress(self.allDoneClass) # 所有进度入库

        headers = {
            "Origin": "https://admin-jiangxi.zhipeizaixian.com",
            "X-User-Type": "1",
        }
        newHeaders = {**self.session.headers, **headers}
        response = self.guaranteeRequest("GET",
                                         self.UrlPool['previewUrl'].format(
                                                 courseId=classInfo.get('courseId'),
                                                 class_id=classInfo.get('class_id')
                                         ),
                                         headers=newHeaders)
        if response.status_code == 200:
            data = response.json()
            analysisPreview(data, classInfo.get('class_id'))
        elif response.status_code == 401:
            publicKey = self.getPublicKey()
            self.getLoginToken(publicKey)
            self.updateAccessToken()
            self.getAllcoursesPreview(classInfo)
        else:
            print(f"我来了2{response.status_code}")
            self.logger.debug(f"时间:{Utils.getFormatted_datetime_now()},当前刷课用户: {self.nickName}, 当前: 获取课程组失败 响应结果:{response.content} 正在等待5秒后重试....")
            self.unifiedErrorSleep()
            self.getAllcoursesPreview(classInfo)

    # @calculate_execution_time(1, "实现课程进度修改")
    def saveDbProgress(self, info: []):
        """将数据存到数据库, 单独实现课程进度修改"""
        if len(info) > 0:
            self.saveVideoProgress(info)

    # @calculate_execution_time(1, "更新视频进度")
    def updateProgress(self):
        """
            更新视频进度 考虑直接使用多线程进行刷的话大概率会被封号,还是单个刷吧
            视频更新前先把数据保存在数据库里面
        """
        def setProgressVideo(info:dict): # total_time = 2872 progress_time = 2340
            # 插入本地时间
            one_videoDetail = self.querOneVideoDeatils(self.idCar, video_id)
            progress_time = one_videoDetail.get("progress_time")
            copyprogress_time = copy(progress_time)
            sum = 0
            queryDate = self.query_sleep_time({
                "video_id": video_id,
                "idCar": self.idCar
            })
            is60Seconds, seconds = Utils.check_local_time_exceed_60_seconds(queryDate[0].get("time"))
            # 判断是否超过60秒，如果没有的话强制等待
            if not is60Seconds:
                """防止已经更新过进度,间隔不到60的, 需要等待60秒再开始"""
                seconds = 60 - seconds
                print(f"时间:{Utils.getFormatted_datetime_now()},当前刷课用户: {self.nickName}, 当前剩余实际按: ", seconds)
                while seconds > 0:
                    seconds -= 1
                    self.logger.info(f"时间:{Utils.getFormatted_datetime_now()},当前刷课用户: {self.nickName}, 防止已经更新过进度,间隔不到60的, 需要等待60秒再开始, 当前剩余时间{seconds}")
                    time.sleep(1)
            while int(info.get("total_time")) > int(progress_time):

                total_time = Utils.getseconds_time(info.get("total_time"))
                difference = int(info.get("total_time")) - int(info['progress_time'])
                self.logger.info(f"时间:{Utils.getFormatted_datetime_now()},当前刷课用户: {self.nickName}, total_time: {info.get('total_time')}, progress_time: {progress_time}, 相差: {difference}")
                progressTime = Utils.getseconds_time(info.get("progress_time"))
                sum += 1
                time.sleep(1)
                if difference > 60:
                    progress_time += 1

                aa = int(info.get("total_time")) - progress_time
                print(f"时间:{Utils.getFormatted_datetime_now()},当前刷课用户: {self.nickName},total_time: {info.get('total_time')} - progress_time:{progress_time}={aa}, sum = {sum}")
                if aa < 60 and sum == 60:
                    print("最后一条片段")
                    cha = int(info.get("total_time")) - progress_time
                    self.logger.info(f"需要等待{cha}秒")
                    time.sleep(cha) # 等待相差时间
                    progress_time += cha
                    self.logger.info(f"最后一条片段: {progress_time}")


                self.logger.info(f"时间:{Utils.getFormatted_datetime_now()},当前刷课用户: {self.nickName}, 刷课标题是: {info.get('title')}, 当前视频时常是: {total_time}, 当前已经到刷了 {progress_time}， 已经播放了{sum}秒。"
                                 f"更新进度时间是: {Config.EVERY_OTHER_PROGRESSVIDEOTIME}, 已经累加进度{ progress_time}")
                if sum == Config.EVERY_OTHER_PROGRESSVIDEOTIME:
                    """每N秒更新一次, 请看配置类， 更新完毕后重置更新时间, 并更新数据库"""
                    headers = {
                        "Host": "apif.wozhipei.com",
                        "Origin": "https://jiangxi.zhipeizaixian.com",
                        "Sec-Fetch-Dest": "empty",
                        "Sec-Fetch-Mode": "cors",
                        "Sec-Fetch-Site": "cross-site",
                        "X-Client-Type": "pc",
                        "X-Site-Alias": "jx",
                        "X-User-Type": "1",
                    }
                    newHeaders = {**self.session.headers, **headers}

                    response = self.guaranteeRequest("POST", self.UrlPool.get("updateProgress").format(
                        video_id=info.get("video_id"),
                        u=info.get("u"),
                        time=progress_time,
                        unit_id=info.get("id"),
                        class_id=info.get("class_id")
                    ),  headers=newHeaders)

                    self.logger.info(f"时间:{Utils.getFormatted_datetime_now()},当前刷课用户: {self.nickName}, 进度发送成功! info: {info}, 响应体: {response.content.decode('utf-8')}")
                    res = response.json()
                    if res['code'] == 555:
                        self.update_Video_data(
                            {
                                "idCar": self.idCar,
                                "video_id": info.get("video_id"),
                                "progress_time": progress_time
                            }
                        )
                        self.update_sleep_time({ #更新视频进度时间
                            "time": time.time(),
                            "video_id": video_id,
                            "idCar": self.idCar
                        })
                    elif response.status_code == 401:
                        publicKey = self.getPublicKey()
                        self.getLoginToken(publicKey)
                        self.updateAccessToken()
                        self.logger.info(f"{Utils.getFormatted_datetime_now()},已经更新验证码, 当前刷课用户: {self.nickName},上传进度没有权限, 已经重新获取权限")
                        self.logger.info(
                            f"时间:{Utils.getFormatted_datetime_now()},初始copyprogress_time: {copyprogress_time}, 叠加后: {progress_time}")
                        progress_time = copyprogress_time
                        self.logger.info(f"{self.nickName}重新登录.时间:{Utils.getFormatted_datetime_now()},重置后: {progress_time} ookk")
                        self.logger.info(
                            f"时间:{Utils.getFormatted_datetime_now()},当前刷课用户: {self.nickName}, {info.get('title')}更新失败 VideoId={info.get('video_id')},已重置{progress_time} 信息{response.content.decode('utf-8')}")

                    elif res['code'] == 2002:
                        print(f"时间:{Utils.getFormatted_datetime_now()},需要识别验证码")
                        code = self.supervisesCode(info.get("class_id"), info.get("course_id"), info.get("id"))
                        response = self.guaranteeRequest("POST", self.UrlPool.get("updateProgress").format(
                            video_id=info.get("video_id"),
                            u=info.get("u"),
                            time=progress_time,
                            unit_id=info.get("id"),
                            class_id=info.get("class_id")
                        ), headers=newHeaders)
                        self.logger.info(
                            f"时间:{Utils.getFormatted_datetime_now()},已经更新验证码, 当前刷课用户: {self.nickName}, 进度发送成功! info: {info}, 响应体: {response.content.decode('utf-8')}")
                        res = response.json()
                        if res['code'] == 555:
                            self.update_Video_data(
                                {
                                    "idCar": self.idCar,
                                    "video_id": info.get("video_id"),
                                    "progress_time": progress_time
                                }
                            )
                            self.update_sleep_time({  # 更新视频进度时间
                                "time": time.time(),
                                "video_id": video_id,
                                "idCar": self.idCar
                            })
                            self.logger.info(f"时间:{Utils.getFormatted_datetime_now()},验证码识别完了: {code}")
                        elif response.status_code == 401:
                            publicKey = self.getPublicKey()
                            self.getLoginToken(publicKey)
                            self.updateAccessToken()
                            progress_time = copyprogress_time
                            self.logger.info(
                                f"{self.nickName}重新登录.时间:{Utils.getFormatted_datetime_now()},重置后: {progress_time} ookk")
                            self.logger.info(
                                f"时间:{Utils.getFormatted_datetime_now()},当前刷课用户: {self.nickName}, {info.get('title')}更新失败 VideoId={info.get('video_id')},已重置{progress_time} 信息{response.content.decode('utf-8')}")

                    elif res['code'] == 2003:

                        def getNot2003():
                            headers = {
                                "Host": "apif.wozhipei.com",
                                "Origin": "https://jiangxi.zhipeizaixian.com",
                                "Sec-Fetch-Dest": "empty",
                                "Sec-Fetch-Mode": "cors",
                                "Sec-Fetch-Site": "cross-site",
                                "X-Client-Type": "pc",
                                "X-Site-Alias": "jx",
                                "X-User-Type": "1",
                            }
                            getNot2003Headers = {**self.session.headers, **headers}
                            response = self.guaranteeRequest("POST", self.UrlPool.get("updateProgress").format(
                                video_id=info.get("video_id"),
                                u=info.get("u"),
                                time=progress_time,
                                unit_id=info.get("id"),
                                class_id=info.get("class_id")
                            ), headers=getNot2003Headers)
                            self.logger.info(f"{Utils.getFormatted_datetime_now()},已经更新验证码, 当前刷课用户: {self.nickName},人脸识别, 已经重新获取权限")
                            return int(response.json()['code'])

                        renCode = int(res['code'])
                        while renCode == 2003:
                            with open("pop.log", "a") as f:
                                f.write(f"时间:{Utils.getFormatted_datetime_now()}用户: {self.nickName},我在等人脸检测.........\n")
                            self.sendMiaoMiao(self.miaomiao)
                            self.logger.info(f"已经通知,用户: {self.nickName},我在等人脸检测.........")
                            time.sleep(360) # 等待6分钟
                            publicKey = self.getPublicKey()
                            self.getLoginToken(publicKey)
                            self.updateAccessToken()
                            self.logger.info(f"用户: {self.nickName},已经重新登录.........")
                            renCode = getNot2003()
                            with open("pop.log", "a") as f:
                                f.write(f"时间:{Utils.getFormatted_datetime_now()}用户: {self.nickName},我在等人脸检测，重新登录了.........状态码: {renCode}\n")
                            if renCode == 555:
                                with open("pop.log", "a") as f:
                                    f.write(
                                        f"时间:{Utils.getFormatted_datetime_now()},用户: {self.nickName}, 人脸检测通过 \n")
                        if renCode != 555:
                            progress_time = copyprogress_time
                            self.logger.info(f"{self.nickName}重新登录.时间:{Utils.getFormatted_datetime_now()},重置后: {progress_time} ookk")
                            self.logger.info(
                                f"时间:{Utils.getFormatted_datetime_now()},当前刷课用户: {self.nickName}, {info.get('title')}更新失败 VideoId={info.get('video_id')},已重置{progress_time} 信息{response.content.decode('utf-8')}")
                    else:
                        print(f"时间:{Utils.getFormatted_datetime_now()},初始copyprogress_time: {copyprogress_time}, 叠加后: {progress_time}")
                        progress_time = copyprogress_time
                        print(f"时间:{Utils.getFormatted_datetime_now()},重置后: {progress_time} ookk")
                        self.logger.info(f"时间:{Utils.getFormatted_datetime_now()},当前刷课用户: {self.nickName}, {info.get('title')}更新失败 VideoId={info.get('video_id')},已重置{progress_time} 信息{response.content.decode('utf-8')}")

                    sum = 0
                    self.logger.info(f"时间:{Utils.getFormatted_datetime_now()},当前刷课用户: {self.nickName}, 数据库已经更新到{progressTime}分钟, 当前秒数已经重置")

        unDoninfos = self.querAllProgressUndonInfo(self.idCar) # 获取所有未完成的课程
        if len(unDoninfos) > 0:
            for undone in unDoninfos:
                print(undone)
                video_id = undone.get("video_id")
                u = undone.get("uid")
                id = undone.get("id")
                class_id = undone.get("class_id")

                title = undone.get("title")
                progress_time = int(undone.get("progress_time"))
                total_time = int(undone.get("total_time"))
                course_id = int(undone.get("course_id"))
                info = {
                    "video_id":video_id,
                    "u":u,
                    "id":id,
                    "class_id":class_id,
                    "total_time": total_time,
                    "progress_time": progress_time,
                    "title": title,
                    "course_id": course_id,
                }

                queryDate = self.query_sleep_time({
                    "video_id": video_id,
                    "idCar": self.idCar
                })

                if len(queryDate) <= 0:
                    # 如果没有的话就插入
                    self.set_sleep_time({
                        "time": time.time(),
                        "video_id":video_id,
                        "idCar": self.idCar
                    })

                setProgressVideo(info)
                # self.updateAccessToken()  # 观看完一个视频后刷新token时间

    def superPeovisesCode(self, nickName, info):
        image_path = f"faces/{nickName}.jpg"
        base64_str = self.image_to_base64(image_path)
        url = "https://apif.wozhipei.com/supervises"
        headers = {
            "Host": "apif.wozhipei.com",
            "Origin": "https://admin-jiangxi.zhipeizaixian.com",
            "X-User-Type": "1",
        }
        jsonData = {
            "baseImage": base64_str,
            "class_id": info.get("class_id"),
            "course_id": info.get("course_id"),
            "unit_id": info.get("id"),
        }
        newHeaders = {**self.session.headers, **headers}
        response = self.session.post(url, headers=newHeaders, json=jsonData)
        res = response.json()
        if res['code'] == 200:
            print(f"{self.nickName}, 识别人脸信息: {res['res']}, 响应体{res}")
            return True, res
        else:
            print(f"{self.nickName}, 识别人脸信息: {res}")
            return False, res
    def image_to_base64(self, image_path):
        with open(image_path, "rb") as image_file:
            encoded_string = base64.b64encode(image_file.read()).decode('utf-8')
        return encoded_string

    def supervisesCode(self, class_id, course_id, unit_id):
        # try:
        headers = {
            "Host": "apif.wozhipei.com",
            "Origin": "https://admin-jiangxi.zhipeizaixian.com",
            "X-User-Type": "1",
        }
        newHeaders = {**self.session.headers, **headers}
        print(f"时间:{Utils.getFormatted_datetime_now()},我来到了超级鹰这里")
        response =self.session.get(self.UrlPool.get("supervisesCode"), headers=newHeaders)
        base64_str = response.content.decode("utf-8").split(",")[1]
        img_data = base64.b64decode(base64_str)
        with open('code.png', 'wb') as f:
            f.write(img_data)
        chaojiying = Chaojiying_Client(Config.chaojiying.get("username"), Config.chaojiying.get("password"), Config.chaojiying.get("soft_id"))  # 用户中心>>软件ID 生成一个替换 96001
        im = open('code.png', 'rb').read()  # 本地图片文件路径 来替换 a.jpg 有时WIN系统须要//
        response = chaojiying.PostPic(im, 6001)  # 1902 验证码类型  官方网站>>价格体系 3.4+版 print 后要加()
        self.logger.info(f"时间:{Utils.getFormatted_datetime_now()},当前刷课用户: {self.nickName}调用超级鹰的接口信息{response}")
        pic_id = response['pic_id']
        pic_str = response['pic_str']
        err_str = response['err_str']
        err_no = response['err_no']
        jsonData = {
            "class_id":class_id,
            "code":pic_str,
            "course_id":course_id,
            "unit_id":unit_id,
        }
        smartNewRes = self.session.post(self.UrlPool.get("smartNew"), headers=newHeaders, json=jsonData)
        self.logger.info(f"时间:{Utils.getFormatted_datetime_now()},当前刷课用户: {self.nickName}验证码识别: 接口返回信息{smartNewRes.content.decode('utf-8')}")
        smart = smartNewRes.json()
        code = smart.get("code")
        if code == 200:
            msg = smart.get("msg")
            self.logger.info(f"时间:{Utils.getFormatted_datetime_now()},当前刷课用户: {self.nickName}验证码识别: {msg}")
            return msg
        else:
            res = chaojiying.ReportError(pic_id)
            self.logger.info(f"时间:{Utils.getFormatted_datetime_now()},当前刷课用户: {self.nickName}验证码识别失败，超级鹰返回: {res}， 将继续识别")
            return self.supervisesCode(class_id, course_id, unit_id) # 5s 后再识别一次
        # except Exception as e :
        #     self.logger.info(f"当前刷课用户: {self.nickName}, 识别过程出现错误, 错误信息{e}")
        #     time.sleep(5)
        #     return self.supervisesCode(class_id, course_id, unit_id) # 5s 后再识别一次

    @calculate_execution_time(1, "刷新token信息")
    def updateAccessToken(self):
        """刷新token信息"""
        headers = {
            "Content-Type": "application/json",
            "Origin": "https://admin-jiangxi.zhipeizaixian.com",
            "Accept": "application/json, text/plain, */*",
            "Accept-encoding": "gzip, deflate, br, zstd",
            "Accept-language": "zh-CN,zh;q=0.9",
            "Cache-control": "no-cache",
            "Referer": "https://admin-jiangxi.zhipeizaixian.com/train-center/mine/student/subPages/student/class",
            "Authorization-platform": self.accessToken
        }
        nowHeaders = {**self.session.headers, **headers}
        response = self.guaranteeRequest("POST", self.UrlPool.get("updateTokenUrl"), headers=nowHeaders, data={})
        if response.json() == True:
            return response
        else:
            self.logger.debug(f"时间:{Utils.getFormatted_datetime_now()},当前刷课用户: {self.nickName}, 当前: 刷新token失败 响应结果:{response.json()}\n请求头:{nowHeaders} 正在等待5秒后重试....")
            self.unifiedErrorSleep()
            self.updateAccessToken()
    def sendMiaoMiao(self, id):
        try:
            res = requests.get(f"http://miaotixing.com/trigger?id={id}")
            print("喵喵: ", res.content.decode("utf-8"))
        except:
            self.logger.debug(f"{self.nickName}, 喵喵提醒失败")


from config import Config
import threading
def run(data):
    flash = FlashClass(data.get("idCar"), data.get("password"), data.get("nickName"), data.get("token"), data.get("miaomiao"))
    # publicKey = flash.getPublicKey()
    # flash.getLoginToken(publicKey)
    # flash.updateAccessToken()
    flash.setSessionHeaders({
                'User-Agent': random.choice(generate_user_agents(100)),
                'Authorization': data.get("token")
            })
    classInfo = flash.getStudentStudy()
    flash.getAllcoursesPreview(classInfo)
    flash.updateProgress()
    print(data)

threadItem = []
for item in Config.userInfo:
    t = threading.Thread(target=run, args=(item,))
    threadItem.append(t)
    t.start()

for i in threadItem:
    i.join()
